/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hu.rsc.feeds.client;

import hu.rsc.feeds.client.data.Category;
import hu.rsc.feeds.client.data.Dictionary;
import hu.rsc.feeds.client.data.Feed;
import hu.rsc.feeds.client.data.InitData;
import hu.rsc.feeds.client.data.UserCategory;
import hu.rsc.feeds.client.data.UserFeed;
import hu.rsc.feeds.client.data.UserInfo;
import hu.rsc.feeds.client.dnd.Position;
import hu.rsc.feeds.client.gui.DragAndDropPanel;
import hu.rsc.feeds.client.gui.LoginPanel;
import hu.rsc.feeds.client.service.RssReaderService;
import hu.rsc.feeds.client.service.RssReaderServiceAsync;
import hu.rsc.feeds.client.util.DictionaryReader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SourcesTabEvents;
import com.google.gwt.user.client.ui.TabListener;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Main entry point.
 * 
 * @author arbuckle
 */
public class Feeds implements EntryPoint {
    private static Long nexNewId = -1l;

    public static final DateTimeFormat DATE_FORMAT_HU = DateTimeFormat.getFormat("yyyy.MM.dd.");
    public static final DateTimeFormat DATE_FORMAT_EN = DateTimeFormat.getFormat("dd.MM.yyyy.");

    public static UserInfo userInfo = null;

    private static InitData initData;

    private static boolean help = false;

    public static native String getBrowserLang() /*-{
        return $wnd.navigator.language;
    }-*/;

    public static DateTimeFormat getDateFormat() {
	return getLanguage().equals(UserInfo.LANG_HU) ? DATE_FORMAT_HU : DATE_FORMAT_EN;
    }

    public static InitData getInitData() {
	return initData;
    }

    public static String getLanguage() {
	if (lang != null && lang.length() != 0) {
	    return lang;
	}
	if (getUserInfo() != null && getUserInfo().getLang() != null) {
	    return getUserInfo().getLang();
	}
	String lang = getBrowserLang();
	if (lang != null && lang.contains(UserInfo.LANG_HU)) {
	    lang = userInfo.LANG_HU;
	} else if (lang != null && lang.contains(UserInfo.LANG_EN)) {
	    lang = UserInfo.LANG_EN;
	} else {
	    lang = UserInfo.LANG_EN;
	}
	return lang;
    }

    public static Long getNextId() {
	nexNewId--;
	return nexNewId;
    }

    public static RssReaderServiceAsync getService() {
	return service;
    }

    public static UserInfo getUserInfo() {
	return userInfo;
    }

    public static boolean isLoggined() {
	return userInfo != null && userInfo.getId() != null && userInfo.getId() > 0;
    }

    private TabPanel tabpanel = new TabPanel();
    private HashMap<String, DragAndDropPanel> tabs = new HashMap<String, DragAndDropPanel>();

    //private DragAndDropPanel centerPanel;
    public static HashMap<Long, Feed> feeds;

    public HashMap<Long, UserFeed> userFeeds = new HashMap<Long, UserFeed>();

    public static RssReaderServiceAsync service;

    private static Frame frame;

    public static Category getCategoryById(Long id) {
	for (Category c : initData.getCategories()) {
	    if (c.getId().equals(id)) {
		return c;
	    }
	}
	return null;
    }

    public List<Category> categories = new ArrayList<Category>();

    public DockPanel main = new DockPanel();

    private int selectedTab = 0;

    public static String lang = null;

    public void addUserFeed(UserFeed uc) {

	String key = uc.getUsercategory() != null ? getUserCategory(uc.getUsercategory()).getLabel() : UserCategory.DEF_TAB;
	DragAndDropPanel dndPanel = this.tabs.get(key);
	if (dndPanel == null) {
	    dndPanel = new DragAndDropPanel(this, getUserCategory(uc.getId()));
	    this.tabpanel.add(dndPanel, key);

	    this.tabs.put(key, dndPanel);
	}
	this.userFeeds.put(uc.getId(), uc);
	dndPanel.addUserFeed(uc);
    }

    public void changeLanguage(final String language) {
	RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, GWT.getModuleBaseURL() + "dictionary/dictionary_" + language + ".xml");
	refreshEastPanel(language);

	try {
	    requestBuilder.sendRequest(null, new RequestCallback() {
		@Override
		public void onError(Request request, Throwable exception) {
		}

		@Override
		public void onResponseReceived(Request request, Response response) {
		    Dictionary.setEntries(DictionaryReader.getDictionary(response.getText()));
		    Dictionary.refresh();
		}
	    });
	} catch (RequestException ex) {
	}

    }

    public Feed getFeedById(Long id) {
	return this.feeds.get(id);
    }

    public Position getFreePosition(Long ucId) {
	String key = ucId != null ? getUserCategory(ucId).getLabel() : UserCategory.DEF_TAB;
	DragAndDropPanel dndp = this.tabs.get(key);
	return dndp.getFreePosition();
    }

    public Widget getNorthPanel() {
	HorizontalPanel hp = new HorizontalPanel();
	hp.setWidth("100%");
	hp.add(new LoginPanel(this));
	return hp;
    }

    public String getSelectedUserCaegory() {
	if (this.selectedTab == 0) {
	    return UserCategory.DEF_TAB;
	}
	return this.initData.getUsercategories().get(this.selectedTab - 1).getLabel();
    }

    @Override
    public void onModuleLoad() {
	String href = Window.Location.getHref();
	String h = null;
	if (href.contains("index_news_en")) {
	    lang = "en";
	    h = "0";
	} else if (href.contains("index_news_hu")) {
	    lang = "hu";
	    h = "0";
	} else if (href.contains("index_help_en")) {
	    lang = "en";
	    h = "1";
	} else if (href.contains("index_help_hu")) {
	    lang = "hu";
	    h = "1";
	} else {
	    lang = com.google.gwt.user.client.Window.Location.getParameter("lng");
	    h = com.google.gwt.user.client.Window.Location.getParameter("help");
	}

	if (h != null) {
	    try {
		if (h.equals("1")) {
		    help = true;
		} else {
		    help = false;
		}
	    } catch (Exception e) {
	    }
	}
	this.service = (RssReaderServiceAsync) GWT.create(RssReaderService.class);

	this.service.doInit(new AsyncCallback<InitData>() {

	    @Override
	    public void onFailure(Throwable caught) {
		// TODO Auto-generated method stub

	    }

	    @Override
	    public void onSuccess(InitData result) {
		Feeds.this.initData = result;
		afterOnModuleLoad();
	    }
	});

    }

    public void refresh(InitData initData) {
	this.userInfo = initData.getUserInfo();
	this.initData = initData;
	this.main.clear();
	this.tabpanel.clear();
	this.userFeeds.clear();
	this.tabs.clear();
	Widget np = getNorthPanel();
	this.main.add(np, DockPanel.NORTH);
	Widget ep = getEastPanel();
	this.main.add(ep, DockPanel.EAST);
	this.main.setCellWidth(np, "100%");
	this.main.setCellHeight(ep, "100%");
	/*this.centerPanel = new DragAndDropPanel(this, null);
	this.tabpanel.add(this.centerPanel, UserCategory.DEF_TAB);*/
	this.main.add(this.tabpanel, DockPanel.CENTER);
	buildTabs();
	getUserFeeds();
	changeLanguage(getLanguage());
    }

    public void removeUserFeed(UserFeed userFeed) {
	this.userFeeds.remove(userFeed.getId());
	String key = userFeed.getUsercategory() != null ? getUserCategory(userFeed.getUsercategory()).getLabel() : UserCategory.DEF_TAB;
	DragAndDropPanel dndPanel = this.tabs.get(key);
	dndPanel.getDropTarget(userFeed.getX(), userFeed.getY()).clear();
	/**
	 * Physical delete
	 */
	if (userFeed.getId() != null) {
	    this.service.deleteUserFeed(userFeed, new AsyncCallback<Void>() {
		@Override
		public void onFailure(Throwable caught) {
		}

		@Override
		public void onSuccess(Void result) {
		}
	    });
	}
    }

    public void save() {
	List<UserFeed> toSave = new ArrayList<UserFeed>();
	toSave.addAll(this.userFeeds.values());

	this.service.saveUserFeeds(toSave, new AsyncCallback<String>() {

	    @Override
	    public void onFailure(Throwable caught) {
		Window.alert(Dictionary.getEntry(Dictionary.MESSAGE_COMM_ERROR, null));
	    }

	    @Override
	    public void onSuccess(String result) {
		Window.alert(Dictionary.getEntry(Dictionary.MESSAGE_SAVE_SUCCESS, null));
	    }
	});
    }

    private void afterOnModuleLoad() {
	RootPanel.get("content").add(this.main);
	this.tabpanel.addTabListener(new TabListener() {

	    @Override
	    public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
		return true;
	    }

	    @Override
	    public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
		Feeds.this.selectedTab = tabIndex;
	    }
	});
	this.main.addStyleName("body");
	getFeeds();

	/*this.centerPanel = new DragAndDropPanel(this, null);*/
    }

    private void buildTabs() {
	DragAndDropPanel mainDnd = new DragAndDropPanel(this, null);
	this.tabs.put(UserCategory.DEF_TAB, mainDnd);
	this.tabpanel.add(mainDnd, UserCategory.DEF_TAB);
	for (UserCategory uc : this.initData.getUsercategories()) {
	    DragAndDropPanel dnd = new DragAndDropPanel(this, uc);
	    this.tabs.put(uc.getLabel(), dnd);
	    this.tabpanel.add(dnd, uc.getLabel());
	}
	this.tabpanel.selectTab(0);
    }

    private Widget getEastPanel() {
	VerticalPanel vp = new VerticalPanel();

	HorizontalPanel buttonPanel = new HorizontalPanel();
	Image helpImage = new Image(GWT.getHostPageBaseURL() + "images/help.png");
	helpImage.addClickHandler(new ClickHandler() {

	    @Override
	    public void onClick(ClickEvent event) {
		help = true;
		refreshEastPanel(null);
	    }
	});
	helpImage.setSize("30px", "30px");
	Image newsImage = new Image(GWT.getHostPageBaseURL() + "images/news.jpg");
	newsImage.addClickHandler(new ClickHandler() {

	    @Override
	    public void onClick(ClickEvent event) {
		help = false;
		refreshEastPanel(null);

	    }
	});
	newsImage.setSize("30px", "30px");
	buttonPanel.add(helpImage);
	buttonPanel.add(newsImage);
	vp.add(buttonPanel);
	if (frame == null) {
	    frame = new Frame();
	    frame.setHeight("800px");
	}
	vp.add(frame);
	refreshEastPanel(null);
	return vp;
    }

    private void getFeeds() {
	this.feeds = new HashMap<Long, Feed>();
	AsyncCallback<List<Feed>> callback = new AsyncCallback<List<Feed>>() {

	    @Override
	    public void onFailure(Throwable caught) {
		caught.printStackTrace();
	    }

	    @Override
	    public void onSuccess(List<Feed> result) {
		for (Feed c : result) {
		    Feeds.this.feeds.put(c.getId(), c);
		}

		render();
	    }
	};
	this.service.getFeeds(callback);
    }

    private UserCategory getUserCategory(Long id) {
	UserCategory uc = null;
	for (UserCategory c : this.initData.getUsercategories()) {
	    if (c.getId().equals(id)) {
		return c;
	    }
	}
	return uc;
    }

    private void getUserFeeds() {
	AsyncCallback<List<UserFeed>> callback = new AsyncCallback<List<UserFeed>>() {

	    @Override
	    public void onFailure(Throwable caught) {
		caught.printStackTrace();
	    }

	    @Override
	    public void onSuccess(List<UserFeed> result) {
		for (UserFeed uf : result) {
		    Feeds.this.addUserFeed(uf);
		    //Feeds.this.userFeeds.put(uf.getId(), uf);

		}
		//Feeds.this.centerPanel.addUserFeeds(Feeds.this.userFeeds.values());
	    }
	};
	this.service.getUserFeeds(callback);
    }

    private void refreshEastPanel(String lang) {
	String url = GWT.getModuleBaseURL();
	if (help) {
	    url += "help";
	} else {
	    url += "whatisnew";
	}
	url += "?app=rssfeeds&lang=" + (lang == null ? getLanguage() : lang);
	if (frame == null) {
	    frame = new Frame();
	}
	frame.setUrl(url);
    }

    private void render() {
	this.main.add(getNorthPanel(), DockPanel.NORTH);
	Widget ep = getEastPanel();
	this.main.add(ep, DockPanel.EAST);
	this.main.setCellHeight(ep, "100%");
	//this.tabpanel.add(this.centerPanel, UserCategory.DEF_TAB);
	this.main.add(this.tabpanel, DockPanel.CENTER);
	this.tabpanel.setAnimationEnabled(true);

	buildTabs();

	getUserFeeds();
	changeLanguage(getLanguage());

	service.isLoggined(new AsyncCallback<Boolean>() {

	    @Override
	    public void onFailure(Throwable caught) {
	    }

	    @Override
	    public void onSuccess(Boolean result) {
		if (result) {
		    service.autenticate(null, null, new AsyncCallback<InitData>() {

			@Override
			public void onFailure(Throwable caught) {
			    Window.alert(Dictionary.getEntry(Dictionary.MESSAGE_INVALID_LOGIN, null));
			}

			@Override
			public void onSuccess(InitData result) {
			    if (result != null && result.getUserInfo() != null) {
				Feeds.this.refresh(result);
			    } else {
				Window.alert(Dictionary.getEntry(Dictionary.MESSAGE_INVALID_LOGIN, null));
			    }
			}
		    });
		}
	    }
	});

    }

}
